#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
编译目标注册表
管理所有编译目标的注册和查询
"""

from typing import Dict, List, Set, Optional
from enum import Enum
import logging

class TargetType(Enum):
    """编译目标类型"""
    EXECUTABLE = "executable"      # 可执行文件
    SHARED_LIBRARY = "shared_lib"  # 动态库
    STATIC_LIBRARY = "static_lib"  # 静态库
    OBJECT_FILES = "objects"       # 目标文件
    PREBUILT_STATIC_LIBRARY = "prebuilt_static_lib"  # 预编译静态库
    PREBUILT_SHARED_LIBRARY = "prebuilt_shared_lib"  # 预编译动态库
    HEADER_LIBRARY = "header_lib"  # 头文件库
    PROTO_LIBRARY = "proto_lib"    # Protocol Buffers库

class BuildTarget:
    """编译目标类"""

    def __init__(self, name: str, target_type: TargetType,
                 sources: List[str], module_path: str):
        """
        初始化编译目标

        Args:
            name: 目标名称
            target_type: 目标类型
            sources: 源文件列表
            module_path: 所属Module路径
        """
        self.name = name
        self.target_type = target_type
        self.sources = sources
        self.module_path = module_path
        self.dependencies = []  # 依赖的其他目标
        self.shared_libs = []  # 链接的动态库
        self.static_libs = []  # 链接的静态库
        self.lib_paths = []    # 库搜索路径
        self.include_paths = [] # 头文件搜索路径
        self.export_include_paths = [] # 导出的头文件搜索路径
        self.defines = []      # 预处理宏定义
        self.cflags = []       # C编译选项
        self.cxxflags = []     # C++编译选项
        self.ldflags = []      # 链接选项
        self.output_dir = ""   # 输出目录
        self.install_dir = ""  # 安装目录
        self.library_path = "" # 预编译库文件路径（仅用于预编译库）

        # Proto相关属性
        self.proto_files = []  # proto文件列表
        self.proto_type = "full"  # proto类型：full/lite/min
        self.proto_path = ""   # proto文件搜索路径
        self.generated_sources = []  # 生成的源文件
        self.generated_headers = []  # 生成的头文件

    def add_dependency(self, target_name: str):
        """添加依赖目标"""
        if target_name not in self.dependencies:
            self.dependencies.append(target_name)

    def add_shared_lib(self, lib_name: str):
        """添加动态库"""
        if lib_name not in self.shared_libs:
            self.shared_libs.append(lib_name)

    def add_static_lib(self, lib_name: str):
        """添加静态库"""
        if lib_name not in self.static_libs:
            self.static_libs.append(lib_name)



    def add_lib_path(self, lib_path: str):
        """添加库搜索路径"""
        if lib_path not in self.lib_paths:
            self.lib_paths.append(lib_path)

    def add_include_path(self, include_path: str):
        """添加头文件搜索路径"""
        if include_path not in self.include_paths:
            self.include_paths.append(include_path)

    def add_export_include_path(self, export_include_path: str):
        """添加导出的头文件搜索路径"""
        if export_include_path not in self.export_include_paths:
            self.export_include_paths.append(export_include_path)

    def add_define(self, define: str):
        """添加预处理宏定义"""
        if define not in self.defines:
            self.defines.append(define)

    def __str__(self):
        return f"BuildTarget(name={self.name}, type={self.target_type.value}, sources={len(self.sources)})"

class TargetRegistry:
    """编译目标注册表"""

    def __init__(self):
        self.targets: Dict[str, BuildTarget] = {}
        self.target_groups: Dict[str, List[str]] = {}  # 目标分组

    def register_target(self, target: BuildTarget) -> bool:
        """
        注册编译目标

        Args:
            target: 编译目标

        Returns:
            是否注册成功
        """
        if target.name in self.targets:
            logging.warning(f"目标 '{target.name}' 已存在，将被覆盖")

        self.targets[target.name] = target
        return True

    def get_target(self, name: str) -> Optional[BuildTarget]:
        """
        获取编译目标

        Args:
            name: 目标名称

        Returns:
            编译目标或None
        """
        return self.targets.get(name)

    def has_target(self, name: str) -> bool:
        """
        检查目标是否存在

        Args:
            name: 目标名称

        Returns:
            是否存在
        """
        return name in self.targets

    def get_all_targets(self) -> List[str]:
        """
        获取所有目标名称

        Returns:
            目标名称列表
        """
        return list(self.targets.keys())

    def get_targets_by_type(self, target_type: TargetType) -> List[BuildTarget]:
        """
        按类型获取目标

        Args:
            target_type: 目标类型

        Returns:
            目标列表
        """
        return [target for target in self.targets.values()
                if target.target_type == target_type]

    def get_targets_by_module(self, module_path: str) -> List[BuildTarget]:
        """
        按Module路径获取目标

        Args:
            module_path: Module路径

        Returns:
            目标列表
        """
        return [target for target in self.targets.values()
                if target.module_path == module_path]

    def create_target_group(self, group_name: str, target_names: List[str]):
        """
        创建目标分组

        Args:
            group_name: 分组名称
            target_names: 目标名称列表
        """
        self.target_groups[group_name] = target_names

    def get_target_group(self, group_name: str) -> List[str]:
        """
        获取目标分组

        Args:
            group_name: 分组名称

        Returns:
            目标名称列表
        """
        return self.target_groups.get(group_name, [])

    def resolve_dependencies(self, target_name: str) -> List[str]:
        """
        解析目标依赖关系

        Args:
            target_name: 目标名称

        Returns:
            依赖目标列表（按依赖顺序）
        """
        visited = set()
        result = []

        def _resolve(name: str):
            if name in visited:
                return

            visited.add(name)
            target = self.get_target(name)
            if target:
                for dep in target.dependencies:
                    _resolve(dep)
                result.append(name)

        _resolve(target_name)
        return result[:-1]  # 排除自己

    def validate_dependencies(self) -> List[str]:
        """
        验证所有目标的依赖关系

        Returns:
            错误信息列表
        """
        errors = []

        for target_name, target in self.targets.items():
            for dep in target.dependencies:
                if dep not in self.targets:
                    errors.append(f"目标 '{target_name}' 依赖的目标 '{dep}' 不存在")

        return errors

    def print_summary(self):
        """打印目标摘要"""
        logging.info(f"\n=== 编译目标摘要 ===")
        logging.info(f"总目标数: {len(self.targets)}")

        by_type = {}
        for target in self.targets.values():
            target_type = target.target_type.value
            by_type[target_type] = by_type.get(target_type, 0) + 1

        for target_type, count in by_type.items():
            logging.info(f"  {target_type}: {count}")

        if self.target_groups:
            logging.info(f"\n目标分组: {len(self.target_groups)}")
            for group_name, targets in self.target_groups.items():
                logging.info(f"  {group_name}: {targets}")